﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;


public static class StringExtension
{
    /// <summary>
    /// 指示指定的字符串是 null 还是 System.String.Empty 字符串
    /// </summary>
    /// <param name="value">要测试的字符串</param>
    /// <returns>如果 value 参数为 null 或空字符串 ("")，则为 true；否则为 false</returns>
    public static bool IsNullOrEmpty(this string value)
    {
        return string.IsNullOrEmpty(value);
    }

    /// <summary>
    /// 指示指定的字符串是 null、空还是仅由空白字符组成
    /// </summary>
    /// <param name="value">要测试的字符串</param>
    /// <returns>如果 value 参数为 null 或 System.String.Empty，或者如果 value 仅由空白字符组成，则为 true</returns>
    public static bool IsNullOrWhiteSpace(this string value)
    {
        return string.IsNullOrWhiteSpace(value);
    }

    /// <summary>
    /// 将字符串转为对应枚举类型
    /// </summary>
    public static T ToEnum<T>(this string strEnum, T defEnum) where T : struct
    {
        T v;
        if (Enum.TryParse<T>(strEnum, out v))
        {
            return v;
        }
        return defEnum;
    }

    /// <summary>
    /// Camel格式
    /// </summary>
    /// <param name="s">要格式化字符</param>
    /// <returns>Camel格式格式后字符</returns>
    public static string ToCamel(this string s)
    {
        if (s.IsNullOrEmpty()) return s;
        return s[0].ToString().ToLower() + s.Substring(1);
    }

    /// <summary>
    /// Pascal格式
    /// </summary>
    /// <param name="s">要格式化字符</param>
    /// <returns>Pascal格式格式后字符</returns>
    public static string ToPascal(this string s)
    {
        if (s.IsNullOrEmpty()) return s;
        return s[0].ToString().ToUpper() + s.Substring(1);
    }


    /// <summary>
    /// 转全角(SBC case)
    /// </summary>
    /// <param name="input">任意字符串</param>
    /// <returns>全角字符串</returns>
    public static string ToSBC(this string input)
    {
        char[] c = input.ToCharArray();
        for (int i = 0; i < c.Length; i++)
        {
            if (c[i] == 32)
            {
                c[i] = (char)12288;
                continue;
            }
            if (c[i] < 127)
                c[i] = (char)(c[i] + 65248);
        }
        return new string(c);
    }
    /// <summary>
    /// 转半角(DBC case)
    /// </summary>
    /// <param name="input">任意字符串</param>
    /// <returns>半角字符串</returns>
    public static string ToDBC(this string input)
    {
        char[] c = input.ToCharArray();
        for (int i = 0; i < c.Length; i++)
        {
            if (c[i] == 12288)
            {
                c[i] = (char)32;
                continue;
            }
            if (c[i] > 65280 && c[i] < 65375)
                c[i] = (char)(c[i] - 65248);
        }
        return new string(c);
    }


    /// <summary>
    /// 字符串的Md5值
    /// </summary>
    public static string Md5Hash(this string input)
    {
        if (input == null)
        {
            return null;
        }

        MD5 md5Hash = MD5.Create();

        // 将输入字符串转换为字节数组并计算哈希数据
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        // 创建一个 Stringbuilder 来收集字节并创建字符串
        StringBuilder sBuilder = new StringBuilder();

        // 循环遍历哈希数据的每一个字节并格式化为十六进制字符串
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        // 返回十六进制字符串
        return sBuilder.ToString();
    }

    /// <summary>
    /// 调用String.Format 方法
    /// </summary>
    public static string Format(this string input, params object[] args)
    {
        return string.Format(input, args);
    }

    /// <summary>
    /// 获取字符串长度（中文按2个字节长度）
    /// </summary>
    /// <param name="stringWithEnglishAndChinese"></param>
    /// <returns></returns>
    public static int DataLength(this string stringWithEnglishAndChinese)
    {
        int lng = 0;
        for (int i = 0; i < stringWithEnglishAndChinese.Length; i++)
        {
            byte[] b = System.Text.Encoding.Default.GetBytes(stringWithEnglishAndChinese.Substring(i, 1));
            if (b.Length > 1)
                lng += 2;
            else
                lng += 1;
        }
        return lng;
    }

    /// <summary>
    /// 字符串截取
    /// </summary>
    /// <param name="str">需要截取的字符串</param>
    /// <param name="maxlen">截取长度(一个中文按2个长度)</param>
    /// <param name="defaultchar">是否需要以......返回</param>
    /// <returns></returns>
    public static string Substr(this string str, int maxlen, bool defaultchar = true)
    {
        if (string.IsNullOrEmpty(str))
        {
            return string.Empty;
        }
        if (maxlen < 1)
        {
            throw new ArgumentException("不能小于1！", "maxlen");
        }
        string result = string.Empty;
        int lng = 0;
        for (int i = 0; i < str.Length; i++)
        {
            byte[] b = Encoding.Default.GetBytes(str.Substring(i, 1));

            if (lng < maxlen)
            {
                if (b.Length > 1)
                    lng += 2;
                else
                    lng += 1;
            }
            else
            {
                return str.Substring(0, i) + (defaultchar ? "......" : string.Empty);
            }
        }
        return result;
    }


    /// <summary>
    /// 首字母大写
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string ToUpperFirstword(string value)
    {
        if (string.IsNullOrEmpty(value))
            return string.Empty;

        string result = string.Empty;
        string[] words = value.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
        if (value.Length <= 1)
        {
            return value.ToUpper();
        }
        else if (words.Length <= 1)
        {
            result = value.Substring(0, 1).ToUpper() + value.Substring(1, value.Length - 1).ToLower();
        }
        else
        {
            List<string> lst = new List<string>();
            foreach (string word in words)
            {
                if (!string.IsNullOrEmpty(word))
                {
                    string temp = word.Substring(0, 1).ToUpper() + word.Substring(1, word.Length - 1).ToLower();
                    lst.Add(temp);
                }
            }
            result = string.Join("_", lst);
        }
        return result;
    }




    /// <summary>
    /// 获取字符位置
    /// </summary>
    /// <param name="content">内容</param>
    /// <param name="splitChars">要Split的字符数组</param>
    /// <returns></returns>
    static Dictionary<string, List<int>> GetAllWordIndex(this string content, string[] splitChars)
    {
        content = content.ToLower();
        string[] words = content.Split(splitChars, StringSplitOptions.RemoveEmptyEntries);
        HashSet<string> lstWord = new HashSet<string>(words);
        Dictionary<string, List<int>> dictIndex = new Dictionary<string, List<int>>();
        int startIndex = 0;
        foreach (string wd in lstWord)
        {
            string word = wd.ToLower();
            while (startIndex < content.Length) //如果当前查找的索引位置小于 内容长度，则该字符就可能存在，那么久继续查找
            {
                int findIndex = content.IndexOf(word, startIndex);
                if (findIndex > -1 && !string.IsNullOrEmpty(word))
                {
                    List<int> lstIndex = null;
                    if (dictIndex.TryGetValue(word, out lstIndex))
                    {
                        lstIndex.Add(findIndex);
                        dictIndex.Remove(word);
                        dictIndex.Add(word, lstIndex);
                    }
                    else
                    {
                        lstIndex = new List<int>();
                        lstIndex.Add(findIndex);
                        dictIndex.Add(word, lstIndex);
                    }
                    startIndex = findIndex + word.Length;
                }
                else//当找不到之后，则跳出对于当前字符的查找，继续下一个字符的查找
                {
                    startIndex = 0;
                    break;
                }
            }
        }
        return dictIndex;
    }

    #region 简繁转换第一种方法
    /// <summary>
    /// 字符串简体转繁体
    /// 使用：需引用 Microsoft.VisualBasic.dll
    /// </summary>
    /// <param name="strSimple"></param>
    /// <returns></returns>
    public static string ToTraditionalChinese(this string strSimple)
    {
        string strTraditional = Microsoft.VisualBasic.Strings.StrConv(strSimple, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, 0);
        return strTraditional;
    }

    /// <summary>
    /// 字符串繁体转简体
    /// 使用：需引用 Microsoft.VisualBasic.dll
    /// </summary>
    /// <param name="strTraditional"></param>
    /// <returns></returns>
    public static string ToSimplifiedChinese(this string strTraditional)
    {
        string strSimple = Microsoft.VisualBasic.Strings.StrConv(strTraditional, Microsoft.VisualBasic.VbStrConv.SimplifiedChinese, 0);
        return strSimple;
    }
    #endregion

    #region 简繁转换第二种方法
    private static Encoding GB2312 = Encoding.GetEncoding(0x3a8);
    private const int LCMAP_SIMPLIFIED_CHINESE = 0x2000000;
    private const int LCMAP_TRADITIONAL_CHINESE = 0x4000000;

    [DllImport("kernel32.dll", EntryPoint = "LCMapStringA")]
    private static extern int LCMapString(int Locale, int dwMapFlags, byte[] lpSrcStr, int cchSrc, byte[] lpDestStr, int cchDest);
    public static string Convert(this string text, ChineseConversionDirection direction)
    {
        byte[] lpSrcStr = null;
        lpSrcStr = GB2312.GetBytes(text);
        byte[] lpDestStr = new byte[lpSrcStr.Length];
        switch (direction)
        {
            case ChineseConversionDirection.TraditionalToSimplified:
                LCMapString(0x804, LCMAP_SIMPLIFIED_CHINESE, lpSrcStr, -1, lpDestStr, lpSrcStr.Length);
                break;
            case ChineseConversionDirection.SimplifiedToTraditional:
                LCMapString(0x804, LCMAP_TRADITIONAL_CHINESE, lpSrcStr, -1, lpDestStr, lpSrcStr.Length);
                break;
        }
        return GB2312.GetString(lpDestStr);
    } 
    #endregion
}

public enum ChineseConversionDirection
{
    SimplifiedToTraditional,
    TraditionalToSimplified
}
